
package com.lbssoft.datalink;

import com.lbssoft.datalink.model.AuthMsg;
import com.lbssoft.datalink.model.BaseMsg;
import com.lbssoft.datalink.model.Constants;
import com.lbssoft.datalink.model.LoginMsg;
import com.lbssoft.datalink.util.Log;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;

import java.util.concurrent.TimeUnit;

/*
 * @ClassName:  ConnectionWatchdog   
 * @Description: 重连检测狗，当发现当前的链路不稳定关闭之后，进行12次重连 
 * @author: Riven
 * @date:   2017年7月10日 上午9:42:55   
 *     
 * @Copyright: 2017 www.lbssoft.com Inc. All rights reserved. 
 */
@Sharable
public abstract class ConnectionWatchdog2 extends SimpleChannelInboundHandler<BaseMsg> implements TimerTask, ChannelHandlerHolder {
    private final Bootstrap bootstrap;
    private final Timer timer;
    private final int port;

    private final String host;
    private final String appSecret;

    private volatile boolean reconnect = true;
    private int attempts;


    public ConnectionWatchdog2(Bootstrap bootstrap, Timer timer, int port, String host, String appSecret, boolean reconnect) {
        this.bootstrap = bootstrap;
        this.timer = timer;
        this.port = port;
        this.host = host;
        this.appSecret = appSecret;
        this.reconnect = reconnect;
    }

    /**
     * channel链路每次active的时候，将其连接的次数重新☞ 0
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        attempts = 0;
        ctx.fireChannelActive();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Log.info("链接关闭");


        if (reconnect) {
            if (attempts < 12) {
                attempts++;
                Log.info("重连" + attempts + "次");
                //重连的间隔时间会越来越长
                int timeout = 60 << attempts;
                timer.newTimeout(this, timeout, TimeUnit.MILLISECONDS);
            }
        }
        ctx.fireChannelInactive();
    }


    @Override
    protected void messageReceived(ChannelHandlerContext ctx, BaseMsg msg)
            throws Exception {
        // TODO Auto-generated method stub

    }


    public void run(Timeout timeout) throws Exception {

        ChannelFuture future;
        //bootstrap已经初始化好了，只需要将handler填入就可以了
        synchronized (bootstrap) {
            bootstrap.handler(new ChannelInitializer<Channel>() {

                @Override
                protected void initChannel(Channel ch) throws Exception {

                    ch.pipeline().addLast(handlers());
                }
            });
            future = bootstrap.connect(host, port);
        }
        //future对象
        future.addListener(new ChannelFutureListener() {

            public void operationComplete(ChannelFuture f) throws Exception {
                boolean succeed = f.isSuccess();

                //如果重连失败，则调用ChannelInactive方法，再次出发重连事件，一直尝试12次，如果失败则不再重连
                if (!succeed) {
                    Log.info("重连失败");
                    f.channel().pipeline().fireChannelInactive();
                } else {
                    Log.info("重连成功");
                    Constants.setClientId(appSecret);
                    AuthMsg auth = new AuthMsg();
                    auth.setAppsecret(appSecret);
                    f.channel().writeAndFlush(auth);

                }
                Log.info("*************************");
            }
        });

    }

}
